Skip to content

fix(godot-cpp): force-include <cstdlib>, broken on libc++ 22 - #146

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/godot-cpp-llvm22-cstdlib
Aug 4, 2026
Merged

fix(godot-cpp): force-include <cstdlib>, broken on libc++ 22#146
Sunrisepeak merged 1 commit into
mainfrom
fix/godot-cpp-llvm22-cstdlib

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

The bug

compat.godot-cpp's src/godot.cpp calls realloc() and free() while including neither <cstdlib> nor <stdlib.h> — it has been riding on a transitive include all along. libstdc++ and libc++ up to 20 still provide one; libc++ 22 does not:

src/godot.cpp:252:19: error: use of undeclared identifier 'realloc'
src/godot.cpp:270:3:  error: use of undeclared identifier 'free'; did you mean 'DefaultAllocator::free'?

Both 4.5.0 and 10.0.0-rc1 carry it, so the fix is not version-gated.

Why CI is green today

The only LLVM legs are workspace (macos) and workspace (windows), and both pin llvm@20.1.7; the linux leg is gcc. Linux-with-a-newer-libc++ is a combination the matrix never builds, so nothing here ever compiled these sources against a libc++ that had dropped the transitive include.

It surfaced in a real GDExtension project pinned to llvm@22.1.8, which had to work around it with a gcc@16.1.0 pin.

Why a force-include and not a shim header

The translation unit at fault is the package's own. A dependency compiles with its own include path, so nothing a consumer ships can reach it — including the header-shadow mechanism godot-cpp-m uses for its module unit, which only ever applies to that package's TUs. Patching the mirror archive was the other option and was rejected: tools/godot-cpp/repack.sh exists to guarantee the archive is upstream byte-for-byte, and it refuses to publish otherwise.

cxxflags rather than cflags: this package has no C sources, and cflags never reaches a .cpp.

Upstream should of course just add the include; this is the index-side unblock in the meantime.

Verification

mcpp 2026.8.3.3 + llvm@22.1.8 on linux, all previously failing:

compat.godot-cpp 4.5.0        → builds, runs (|v| = 5)
compat.godot-cpp 10.0.0-rc1   → builds, runs (|v| = 5)
import godot_cpp; via godotengine.godot-cpp-m 10.0.0-rc1
                              → "module layer under llvm22: |v|=5 Node2D=16"

And the reporting project, with its gcc@16.1.0 pin lifted:

$ mcpp build -p player     # GDExtension, kind = "shared"
    Finished dev [unoptimized + debuginfo] in 5.40s   → libplayer.so
$ mcpp test -p gamecore
 test result ok. 1 passed; 0 failed

gcc 16 is unaffected (the flag is a no-op there — <cstdlib> was already coming in).

Follow-up worth considering

Nothing in CI would catch a regression, because no leg builds these packages against libc++ ≥ 22. A dedicated member pinned to llvm@22.1.8 would close that, at the cost of another full godot-cpp build per platform — worth deciding separately rather than folding in here.

Design notes: .agents/docs/2026-08-04-add-godot-cpp-10.0.0-rc1.md §8.

src/godot.cpp calls realloc() and free() while including neither <cstdlib>
nor <stdlib.h> -- it has been riding on a transitive include all along.
libstdc++ and libc++ up to 20 still provide one; libc++ 22 does not:

  src/godot.cpp:252: error: use of undeclared identifier 'realloc'
  src/godot.cpp:270: error: use of undeclared identifier 'free'

Both 4.5.0 and 10.0.0-rc1 carry it, so the fix is not version-gated.

CI missed it because the only LLVM legs are macOS and Windows and both pin
llvm@20.1.7, while the linux leg is gcc -- linux-with-a-newer-libc++ is a
combination the matrix never builds. It surfaced in a real GDExtension
project pinned to llvm@22.1.8, which had to pin gcc@16 to work around it.

A force-include rather than a generated shim header: the translation unit at
fault is the PACKAGE's own, and a dependency compiles with its own include
path, so nothing a consumer ships -- including the header-shadow mechanism
godot-cpp-m uses for its module unit -- can reach it. cxxflags rather than
cflags: this package has no C sources and cflags never reaches a .cpp.

Verified with mcpp 2026.8.3.3 + llvm@22.1.8 on linux: compat.godot-cpp 4.5.0
and 10.0.0-rc1 both build and run; `import godot_cpp;` through
godotengine.godot-cpp-m 10.0.0-rc1 builds and runs; and the reporting project
builds its player GDExtension (libplayer.so) with its gcc pin lifted.
@Sunrisepeak
Sunrisepeak merged commit 3b95778 into main Aug 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants